package com.shanghaionstar.remote.service;

import android.content.Context;
import android.util.SparseArray;

import com.onstar.cn.api.PublicService;
import com.onstar.cn.api.VehicleService;
import com.onstar.cn.common.exception.HttpException;
import com.onstar.cn.common.exception.OnStarException;
import com.onstar.cn.common.log.LogManager;
import com.onstar.cn.common.util.CommonUtil;
import com.onstar.cn.common.util.Constants;
import com.onstar.cn.framework.annotation.http.HeadsValue;
import com.onstar.cn.framework.annotation.http.Request;
import com.onstar.cn.framework.mvp.base.core.BaseService;
import com.onstar.cn.framework.network.HttpInjectUtils;
import com.onstar.cn.framework.network.entity.RequestEntity;
import com.onstar.cn.framework.network.enumtype.HttpAccept;
import com.onstar.cn.framework.network.enumtype.HttpMethod;
import com.onstar.cn.framework.network.enumtype.Language;
import com.onstar.cn.framework.network.http.CommonError;
import com.onstar.cn.framework.utils.GsonHelper;
import com.onstar.cn.mag.enumtype.RemoteCommandsType;
import com.onstar.cn.sqlite.entities.PollingEntity;
import com.onstar.cn.vehicle.entity.ErrorInfo;
import com.onstar.cn.vehicle.entity.VehicleAlert;
import com.onstar.cn.vehicle.entity.VehicleCommand;
import com.onstar.cn.vehicle.entity.VehicleLockDoor;
import com.onstar.cn.vehicle.entity.VehicleUnLockDoor;
import com.shanghaionstar.remote.model.RemoteModel;
import com.shanghaionstar.service.VehicleManager;
import com.shanghaionstar.utils.ApplicationUtil;
import com.shanghaionstar.utils.BusinessUtil;
import com.shanghaionstar.utils.ErrorCodeUtil;
import com.shanghaionstar.utils.NetConnectUtil;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import rx.Observable;
import rx.functions.Func0;

/**
 * Created by 6335yz on 2016/6/25.
 */
public class RemoteService extends BaseService {

    private LogManager log = LogManager.getInstance();
    private Context context;
    private VehicleManager manager;

    public RemoteService(Context context) {
        this.context = context;
        manager = new VehicleManager(context, Constants.CURRENT_SERVER_URL);
    }

    @Override
    public String jsonToBean(String json) {
        return json;
    }

    @Override
    public RequestEntity getRequestEntity() {
        return null;
    }


    public Observable<String> initAlertParams() {
        return Observable.defer(new Func0<Observable<String>>() {
            @Override
            public Observable<String> call() {
                try {
                    return Observable.just(alertInit());
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }

    public String alertInit() throws OnStarException {
        RequestEntity requestEntity = new PublicService(Constants.CURRENT_SERVER_URL).alertDuration(null);
        requestEntity.setMethod(HttpMethod.GET.value());
        return NetConnectUtil.getResponse(getDatas(requestEntity));
    }

    public Observable<String> commandByType(final RemoteModel remoteModel) {
        ApplicationUtil.getInstance().isCommanding =true;
        return Observable.defer(new Func0<Observable<String>>() {
            @Override
            public Observable<String> call() {
                try {
                    return Observable.just(command(remoteModel));
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }

    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.POST)
    public String command(final RemoteModel remoteModel) throws OnStarException {
        RemoteCommandsType commandType = remoteModel.getRemoteCommandsType();
        VehicleService service = new VehicleService(Constants.CURRENT_SERVER_URL);
        RequestEntity requestEntity = NetConnectUtil.getAuthRequestEntity(context);
        String body = "";
        if (!CommonUtil.isNull(remoteModel.getBody())) {
            body = remoteModel.getBody();
        } else {
            switch (commandType) {
                case COMMANDS_LOCK_DOOR:
                    body = lock();
                    break;
                case COMMANDS_UNLOCK_DOOR:
                    body = unlock();
                    break;
                case COMMANDS_START:
                    // no body
                    break;
                case COMMANDS_CANCEL_START:
                    // no body
                    break;
                case COMMANDS_ALERT:
                    body = alert(remoteModel.isHorn(), remoteModel.isFlash());
                    break;
                default:
                    break;
            }
        }
        service.commands(requestEntity, commandType, ApplicationUtil.getInstance().getCurrentVehicle().getVin(),body);
        BusinessUtil.initPollingStatusBeforePolling(commandType, ApplicationUtil.getInstance().getCurrentVehicle().getVin(),manager);
        ApplicationUtil.getInstance().isCommanding = false;

        requestEntity = HttpInjectUtils.injectHttp(getClass(), "command", requestEntity, RemoteModel.class);
        SparseArray<String> reseponseData = getDatas(requestEntity);
        if (reseponseData != null && reseponseData.size() != 0) {
            int responseCode = -1;
//            for (Integer key : reseponseData.keySet()) {
//                responseCode = key;
//                break;
//            }
            for (int i = 0; i < reseponseData.size(); i++) {
                responseCode = reseponseData.keyAt(i);
                break;
            }
            if (responseCode != 200 && responseCode != 202) {
                CommonError commonError = GsonHelper.fromJson(reseponseData.get(responseCode),CommonError.class);
                HttpException httpException = new HttpException(commonError.getErrorCode(), commonError.getErrorMessage());
                ErrorInfo errorInfo = ErrorCodeUtil.getErrorInfoByHttpException(context, httpException);
                throw new HttpException(errorInfo.getCode(), errorInfo.getMsg());
            } else {
                //成功请求
                String json = reseponseData.get(responseCode);
                log.d(json);
                JSONObject error = GsonHelper.getJsonObject(json, "error");
                JSONObject commandResponse = GsonHelper.getJsonObject(json, "commandResponse");
                if (error != null) {
                    try {
                        String code = error.getString("code");
                        String description = error.getString("description");
                        ErrorInfo errorInfo = new ErrorInfo();
                        errorInfo.setCode(code);
                        errorInfo.setMsg(description);
                        throw new OnStarException(errorInfo.getCode(), errorInfo.getMsg());
                    } catch (JSONException e) {
                        log.e(e.getMessage());
                        processError(commandType, e);
                    } finally {
                        BusinessUtil.updateToFailPollingStatusBeforePolling(commandType, ApplicationUtil.getInstance().getCurrentVehicle().getVin(),manager);
                    }
                } else if (commandResponse != null) {
                    String url;
                    try {
                        url = commandResponse.getString("url");
                        String requestId = url.substring(url.lastIndexOf("s") + 2, url.length());
                        startPollVehicleStatus(commandType, requestId);
                    } catch (JSONException e) {
                        processError(commandType, e);
                    }
                }
                return json;
            }
        }
        return null;
    }

    private void processError(final RemoteCommandsType commandType, Exception e) throws OnStarException {
        BusinessUtil.updateToFailPollingStatusBeforePolling(commandType, ApplicationUtil.getInstance().getCurrentVehicle().getVin(),manager);
        ErrorInfo errorInfo = BusinessUtil.getErrorInfoByException(context, e);
        throw new OnStarException(errorInfo.getCode(), errorInfo.getMsg());
    }

    public void startPollVehicleStatus(RemoteCommandsType commandsType, String requestId) {
        PollingEntity entity = new PollingEntity();
        entity.setVin(ApplicationUtil.getInstance().getCurrentVehicle().getVin());
        entity.setToken(ApplicationUtil.getInstance().getToken());
        entity.setRequestType(commandsType.value());
        entity.setRequestId(requestId);
        manager.startPoll(entity);
    }

    private String lock() {
        VehicleCommand vecicleCommand = new VehicleCommand();
        VehicleLockDoor lockDoor = new VehicleLockDoor();
        lockDoor.setDelay("0");
        vecicleCommand.setLockDoorRequest(lockDoor);
        return GsonHelper.toJson(vecicleCommand);
    }

    private String unlock() {
        VehicleCommand vecicleCommand = new VehicleCommand();
        VehicleUnLockDoor unlockDoor = new VehicleUnLockDoor();
        unlockDoor.setDelay("0");
        vecicleCommand.setUnlockDoorRequest(unlockDoor);
        return GsonHelper.toJson(vecicleCommand);
    }

    private String alert(boolean isHorn, boolean isFlash) {
        String[] array = new String[]{};
        List<String> list = new ArrayList<String>();
        if (isHorn) {
            list.add("Honk");
        }
        if (isFlash) {
            list.add("Flash");
        }
        VehicleCommand vecicleCommand = new VehicleCommand();
        VehicleAlert alert = new VehicleAlert();
        alert.setDelay("0");
        //		alert.setDuration("60");
        //IDT1 个例只能为30
        alert.setDuration((ApplicationUtil.getInstance().getAlertDuration() != -1 ? ApplicationUtil.getInstance().getAlertDuration() : ApplicationUtil.ALERT_DURATION_DEF) + "");
        alert.setAction(list.toArray(array));
        alert.setOverride(new String[]{"DoorOpen", "IgnitionOn"});
        vecicleCommand.setAlertRequest(alert);
        return GsonHelper.toJson(vecicleCommand);
    }

}
